package com.vladsch.flexmark.core.test.util.html;

import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.test.util.FlexmarkSpecExampleRenderer;
import com.vladsch.flexmark.test.util.RenderingTestCase;
import com.vladsch.flexmark.test.util.SpecExampleRenderer;
import com.vladsch.flexmark.test.util.Strings;
import com.vladsch.flexmark.test.util.spec.SpecExample;
import com.vladsch.flexmark.util.data.DataHolder;
import com.vladsch.flexmark.util.data.DataSet;
import com.vladsch.flexmark.util.data.MutableDataSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Stopwatch;
import org.junit.rules.Timeout;
import org.junit.runner.Description;

import java.util.concurrent.TimeUnit;

public abstract class PathologicalRenderingTestCase extends RenderingTestCase {
    final private DataHolder OPTIONS;

    public PathologicalRenderingTestCase(boolean spcInLinkUrls) {
        OPTIONS = new MutableDataSet()
                .set(Parser.SPACE_IN_LINK_URLS, spcInLinkUrls);
    }

    @Nullable
    @Override
    final public DataHolder options(@NotNull String option) {
        return null;
    }

    @Override
    final public @NotNull SpecExampleRenderer getSpecExampleRenderer(@NotNull SpecExample example, @Nullable DataHolder exampleOptions) {
        DataHolder combinedOptions = DataSet.aggregate(OPTIONS, exampleOptions);
        return new FlexmarkSpecExampleRenderer(example, combinedOptions, Parser.builder(combinedOptions).build(), HtmlRenderer.builder(combinedOptions).build(), true);
    }

    private int x = 100000;

    @Rule
    public Timeout timeout = new Timeout(3, TimeUnit.SECONDS);

    @Rule
    public Stopwatch stopwatch = new Stopwatch() {
        @Override
        protected void finished(long nanos, Description description) {
            System.err.println(description.getDisplayName() + " took " + (nanos / 1000000) + " ms");
        }
    };

    @Test
    public void nestedStrongEmphasis() {
        // this is limited by the stack size because visitor is recursive
        x = 500;
        assertRendering(
                Strings.repeat("*a **a ", x) + "b" + Strings.repeat(" a** a*", x), "<p>" + Strings.repeat("<em>a <strong>a ", x) + "b" +
                        Strings.repeat(" a</strong> a</em>", x) + "</p>\n");
    }

    @Test
    public void emphasisClosersWithNoOpeners() {
        assertRendering(
                Strings.repeat("a_ ", x), "<p>" + Strings.repeat("a_ ", x - 1) + "a_</p>\n");
    }

    @Test
    public void emphasisOpenersWithNoClosers() {
        assertRendering(
                Strings.repeat("_a ", x), "<p>" + Strings.repeat("_a ", x - 1) + "_a</p>\n");
    }

    @Test
    public void linkClosersWithNoOpeners() {
        assertRendering(
                Strings.repeat("a] ", x), "<p>" + Strings.repeat("a] ", x - 1) + "a]</p>\n");
    }

    @Test
    public void linkOpenersWithNoClosers() {
        assertRendering(
                Strings.repeat("[a ", x), "<p>" + Strings.repeat("[a ", x - 1) + "[a</p>\n");
    }

    @Test
    public void linkOpenersAndEmphasisClosers() {
        assertRendering(
                Strings.repeat("[ a_ ", x), "<p>" + Strings.repeat("[ a_ ", x - 1) + "[ a_</p>\n");
    }

    @Test
    public void mismatchedOpenersAndClosers() {
        assertRendering(
                Strings.repeat("*a_ ", x), "<p>" + Strings.repeat("*a_ ", x - 1) + "*a_</p>\n");
    }

    @Test
    public void nestedBrackets() {
        assertRendering(
                Strings.repeat("[", x) + "a" + Strings.repeat("]", x), "<p>" + Strings.repeat("[", x) + "a" + Strings.repeat("]", x) + "</p>\n");
    }

    @Test
    public void longImageLinkTest() {
        try {
            int x = 100;
            assertRendering(
                    Strings.repeat("![image]()\n\n", x)
                    , Strings.repeat("<p><img src=\"\" alt=\"image\" /></p>\n", x));
        } catch (StackOverflowError error) {
            System.err.print("StackOverflow ");
        }
    }

    @Test
    public void longLinkTest() {
        try {
            int x = 100;
            assertRendering(
                    Strings.repeat("[Traceur](https://google.github.io/traceur-compiler/demo/repl.html#%2F%2F%20Traceur%20now%20uses%20regexpu%20%28https%3A%2F%2Fmths.be%2Fregexpu%29%20to%20transpile%20regular%0A%2F%2F%20expression%20literals%20that%20have%20the%20ES6%20%60u%60%20flag%20set%20into%20equivalent%20ES5.%0A%0A%2F%2F%20Match%20any%20symbol%20from%20U%2B1F4A9%20PILE%20OF%20POO%20to%20U%2B1F4AB%20DIZZY%20SYMBOL.%0Avar%20regex%20%3D%20%2F%5B%F0%9F%92%A9-%F0%9F%92%AB%5D%2Fu%3B%20%2F%2F%20Or%2C%20%60%2F%5Cu%7B1F4A9%7D-%5Cu%7B1F4AB%7D%2Fu%60.%0Aconsole.log%28%0A%20%20regex.test%28'%F0%9F%92%A8'%29%2C%20%2F%2F%20false%0A%20%20regex.test%28'%F0%9F%92%A9'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AA'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AB'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AC'%29%20%20%2F%2F%20false%0A%29%3B%0A%0A%2F%2F%20See%20https%3A%2F%2Fmathiasbynens.be%2Fnotes%2Fes6-unicode-regex%20for%20more%20examples%20and%0A%2F%2F%20info.%0A), [Babel](https://babeljs.io/repl/#?experimental=true&playground=true&evaluate=true&code=%2F%2F%20Babel%20now%20uses%20regexpu%20%28https%3A%2F%2Fmths.be%2Fregexpu%29%20to%20transpile%20regular%0A%2F%2F%20expression%20literals%20that%20have%20the%20ES6%20%60u%60%20flag%20set%20into%20equivalent%20ES5.%0A%0A%2F%2F%20Match%20any%20symbol%20from%20U%2B1F4A9%20PILE%20OF%20POO%20to%20U%2B1F4AB%20DIZZY%20SYMBOL.%0Avar%20regex%20%3D%20%2F%5B%F0%9F%92%A9-%F0%9F%92%AB%5D%2Fu%3B%20%2F%2F%20Or%2C%20%60%2F%5Cu%7B1F4A9%7D-%5Cu%7B1F4AB%7D%2Fu%60.%0Aconsole.log%28%0A%20%20regex.test%28'%F0%9F%92%A8'%29%2C%20%2F%2F%20false%0A%20%20regex.test%28'%F0%9F%92%A9'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AA'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AB'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AC'%29%20%20%2F%2F%20false%0A%29%3B%0A%0A%2F%2F%20See%20https%3A%2F%2Fmathiasbynens.be%2Fnotes%2Fes6-unicode-regex%20for%20more%20examples%20and%0A%2F%2F%20info.%0A), and [esnext](https://esnext.github.io/esnext/#%2F%2F%20esnext%20now%20uses%20regexpu%20%28https%3A%2F%2Fmths.be%2Fregexpu%29%20to%20transpile%20regular%0A%2F%2F%20expression%20literals%20that%20have%20the%20ES6%20%60u%60%20flag%20set%20into%20equivalent%20ES5.%0A%0A%2F%2F%20Match%20any%20symbol%20from%20U%2B1F4A9%20PILE%20OF%20POO%20to%20U%2B1F4AB%20DIZZY%20SYMBOL.%0Avar%20regex%20%3D%20%2F%5B%F0%9F%92%A9-%F0%9F%92%AB%5D%2Fu%3B%20%2F%2F%20Or%2C%20%60%2F%5Cu%7B1F4A9%7D-%5Cu%7B1F4AB%7D%2Fu%60.%0Aconsole.log%28%0A%20%20regex.test%28'%F0%9F%92%A8'%29%2C%20%2F%2F%20false%0A%20%20regex.test%28'%F0%9F%92%A9'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AA'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AB'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AC'%29%20%20%2F%2F%20false%0A%29%3B%0A%0A%2F%2F%20See%20https%3A%2F%2Fmathiasbynens.be%2Fnotes%2Fes6-unicode-regex%20for%20more%20examples%20and%0A%2F%2F%20info.%0A) let you try `u` regexps as well as other ES.next features.\n\n", x)
                    , Strings.repeat("<p><a href=\"https://google.github.io/traceur-compiler/demo/repl.html#%2F%2F%20Traceur%20now%20uses%20regexpu%20%28https%3A%2F%2Fmths.be%2Fregexpu%29%20to%20transpile%20regular%0A%2F%2F%20expression%20literals%20that%20have%20the%20ES6%20%60u%60%20flag%20set%20into%20equivalent%20ES5.%0A%0A%2F%2F%20Match%20any%20symbol%20from%20U%2B1F4A9%20PILE%20OF%20POO%20to%20U%2B1F4AB%20DIZZY%20SYMBOL.%0Avar%20regex%20%3D%20%2F%5B%F0%9F%92%A9-%F0%9F%92%AB%5D%2Fu%3B%20%2F%2F%20Or%2C%20%60%2F%5Cu%7B1F4A9%7D-%5Cu%7B1F4AB%7D%2Fu%60.%0Aconsole.log%28%0A%20%20regex.test%28'%F0%9F%92%A8'%29%2C%20%2F%2F%20false%0A%20%20regex.test%28'%F0%9F%92%A9'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AA'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AB'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AC'%29%20%20%2F%2F%20false%0A%29%3B%0A%0A%2F%2F%20See%20https%3A%2F%2Fmathiasbynens.be%2Fnotes%2Fes6-unicode-regex%20for%20more%20examples%20and%0A%2F%2F%20info.%0A\">Traceur</a>, <a href=\"https://babeljs.io/repl/#?experimental=true&amp;playground=true&amp;evaluate=true&amp;code=%2F%2F%20Babel%20now%20uses%20regexpu%20%28https%3A%2F%2Fmths.be%2Fregexpu%29%20to%20transpile%20regular%0A%2F%2F%20expression%20literals%20that%20have%20the%20ES6%20%60u%60%20flag%20set%20into%20equivalent%20ES5.%0A%0A%2F%2F%20Match%20any%20symbol%20from%20U%2B1F4A9%20PILE%20OF%20POO%20to%20U%2B1F4AB%20DIZZY%20SYMBOL.%0Avar%20regex%20%3D%20%2F%5B%F0%9F%92%A9-%F0%9F%92%AB%5D%2Fu%3B%20%2F%2F%20Or%2C%20%60%2F%5Cu%7B1F4A9%7D-%5Cu%7B1F4AB%7D%2Fu%60.%0Aconsole.log%28%0A%20%20regex.test%28'%F0%9F%92%A8'%29%2C%20%2F%2F%20false%0A%20%20regex.test%28'%F0%9F%92%A9'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AA'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AB'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AC'%29%20%20%2F%2F%20false%0A%29%3B%0A%0A%2F%2F%20See%20https%3A%2F%2Fmathiasbynens.be%2Fnotes%2Fes6-unicode-regex%20for%20more%20examples%20and%0A%2F%2F%20info.%0A\">Babel</a>, and <a href=\"https://esnext.github.io/esnext/#%2F%2F%20esnext%20now%20uses%20regexpu%20%28https%3A%2F%2Fmths.be%2Fregexpu%29%20to%20transpile%20regular%0A%2F%2F%20expression%20literals%20that%20have%20the%20ES6%20%60u%60%20flag%20set%20into%20equivalent%20ES5.%0A%0A%2F%2F%20Match%20any%20symbol%20from%20U%2B1F4A9%20PILE%20OF%20POO%20to%20U%2B1F4AB%20DIZZY%20SYMBOL.%0Avar%20regex%20%3D%20%2F%5B%F0%9F%92%A9-%F0%9F%92%AB%5D%2Fu%3B%20%2F%2F%20Or%2C%20%60%2F%5Cu%7B1F4A9%7D-%5Cu%7B1F4AB%7D%2Fu%60.%0Aconsole.log%28%0A%20%20regex.test%28'%F0%9F%92%A8'%29%2C%20%2F%2F%20false%0A%20%20regex.test%28'%F0%9F%92%A9'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AA'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AB'%29%2C%20%2F%2F%20true%0A%20%20regex.test%28'%F0%9F%92%AC'%29%20%20%2F%2F%20false%0A%29%3B%0A%0A%2F%2F%20See%20https%3A%2F%2Fmathiasbynens.be%2Fnotes%2Fes6-unicode-regex%20for%20more%20examples%20and%0A%2F%2F%20info.%0A\">esnext</a> let you try <code>u</code> regexps as well as other ES.next features.</p>\n", x));
        } catch (StackOverflowError error) {
            System.err.print("StackOverflow ");
        }
    }
}
